package org.game.module.chatbo;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;

import org.cfg.DungeonLevelCfg;
import org.cfg.DungeonLevelGroupCfg;
import org.cfg.EndlessCloisterLevelCfg;
import org.cfg.LevelUpCfg;
import org.cfg.MainLineCfg;
import org.cfg.cache.DungeonLevelCfgCache;
import org.cfg.cache.DungeonLevelGroupCfgCache;
import org.cfg.cache.EndlessCloisterLevelCfgCache;
import org.cfg.cache.LevelUpCfgCache;
import org.cfg.cache.MainLineCfgCache;
import org.constant.ChatConstant;
import org.error.GameErrorCode;
import org.game.cache.OnlinePlayerCache;
import org.game.constant.DungeonTypeConstant;
import org.game.db.DbSave;
import org.game.db.bean.DungeonLevel;
import org.game.db.bean.DungeonLevelGroup;
import org.game.db.bean.Hero;
import org.game.db.bean.Player;
import org.game.db.bean.PlayerData;
import org.game.db.cache.DungeonLevelCache;
import org.game.db.proxy.bean.PlayerDataProxy;
import org.game.db.vo.PlayerDataVO.EndlessVO;
import org.game.log.builder.LogDsp;
import org.game.log.dsp.GoodsDsp;
import org.game.manager.DungeonManager;
import org.game.manager.EndlessCloisterManager;
import org.game.manager.GameRechargeManager;
import org.game.manager.HeroManager;
import org.game.manager.ItemManager;
import org.game.manager.PlayerManager;
import org.game.module.chatbo.testcmd.BuildingTest;
import org.game.module.chatbo.testcmd.DatingTest;
import org.game.module.chatbo.testcmd.RoleTest;
import org.game.module.chatbo.testcmd.RoomTest;
import org.game.module.core.Core;
import org.game.module.dungeonbo.DungeonBO;
import org.game.module.elementcollectbo.ElementCollectBO;
import org.game.module.endlesscloisterbo.EndlessCloisterBO;
import org.game.module.fight.dungeom.DungeonCheck;
import org.game.msgBuilder.DungeonMsgBuilder;
import org.game.msgBuilder.EndlessCloisterMsgBuilder;
import org.game.protobuf.c2s.C2SElementCollectMsg;
import org.game.protobuf.s2c.S2CChatMsg.ChatInfo;
import org.game.protobuf.s2c.S2CDungeonMsg.FightOverMsg;
import org.game.protobuf.s2c.S2CEndlessCloisterMsg.RspEndlessCloisterInfo;
import org.game.protobuf.s2c.S2CEndlessCloisterMsg.RspPassStageEndless;
import org.game.protobuf.s2c.S2CItemMsg;
import org.game.protobuf.s2c.S2CLoginMsg.RespServerTime;
import org.game.protobuf.s2c.S2CPlayerMsg.PlayerInfo;
import org.game.protobuf.s2c.S2CShareMsg.RewardsMsg;
import org.game.util.ProtoUnit;
import org.script.ScriptJavaLoader;
import org.utils.RemoteUtil;

import com.google.common.base.Splitter;
import com.google.common.collect.Lists;
import com.sojoys.artifact.core.IServer;
import com.sojoys.artifact.factory.message.IMessage;
import com.sojoys.artifact.manager.MessageManager;
import com.sojoys.artifact.tools.ToolError;
import com.sojoys.artifact.tools.ToolList;
import com.xiaoleilu.hutool.date.DateTime;
import com.xiaoleilu.hutool.date.DateUtil;
import com.xiaoleilu.hutool.log.Log;
import com.xiaoleilu.hutool.log.LogFactory;
import com.xiaoleilu.hutool.system.SystemUtil;
import com.xiaoleilu.hutool.util.MapUtil;
import com.xiaoleilu.hutool.util.StrUtil;

/**
 * @author : DengYing
 * @CreateDate : 2017年10月16日 上午11:17:00
 * @Description ：聊天命令代理
 */
public class ChatCmdProxy {

	static final Log log = LogFactory.get(ChatCmdProxy.class);

	private ChatCmdProxy() {
	}

	private static ChatCmdProxy ME = new ChatCmdProxy();

	public static ChatCmdProxy me() {
		return ME;
	}

	/**
	 * 执行GM命令
	 * 
	 * @param player
	 * @param content
	 * @return
	 */
	public boolean execute(Player player, String content) {
		// 管理员才有命令权限
		if (!IServer.getConstants().isDevMode() && !player.getPlayerProxy().isAdmin())
			return false;
		
		content = content.trim();
		if (content.startsWith("./")) {
			content = content.substring(2);
			List<String> cmds = Splitter.on(StrUtil.SPACE).omitEmptyStrings().splitToList(content);
			if (cmds.isEmpty()) {
				return false;
			}

			String key = ToolList.getString(0, cmds);
			switch (key) {
			case "setDate": {
				String date = ToolList.getString(1, cmds);
				String time = ToolList.getString(2, cmds);
				if (setSystemDate(date, time)) {
					// 设置成功了发送公告
					IMessage msg = notifySystemDate(String.format("<%s> Update System Date -> %s", player.getName(),
							DateUtil.date().toString()));
					OnlinePlayerCache.sendMsgByOnlinePlayer(msg);

					// 更新客户端服务器时间
					RespServerTime.Builder builder = RespServerTime.newBuilder();
					builder.setServerTime((int) (System.currentTimeMillis() / 1000));
					msg = MessageManager.me().create(Core.getServerTime, builder.build().toByteArray());
					OnlinePlayerCache.sendMsgByOnlinePlayer(msg);
				}
				break;
			}
			case "nowDate": {
				IMessage msg = notifySystemDate("System Date : " + DateUtil.date().toString());
				player.getPlayerProxy().sendMsg(msg);
				break;
			}
			case "savedb": {
				try {
					DbSave.saveAll();
					RemoteUtil.socialAsyn().saveDB();
					RemoteUtil.loginAsyn().saveDB();
				} catch (Exception e) {
					e.printStackTrace();
				}
				break;
			}
			case "addItems": {
				int goodsId = ToolList.getInt(1, cmds);
				int num = ToolList.getInt(2, cmds);

				LogDsp log = LogDsp.newBuilder(GoodsDsp.CMD);
				ItemManager.addGoodsAndPush(player, null, null, MapUtil.of(goodsId, num), log);
				break;
			}
			case "delItems": {
				int goodsId = ToolList.getInt(1, cmds);
				int num = ToolList.getInt(2, cmds);

				LogDsp log = LogDsp.newBuilder(GoodsDsp.CMD);
				ItemManager.costGoodsByCid(player, MapUtil.of(goodsId, num), log, S2CItemMsg.ItemList.newBuilder());
				break;
			}
			case "setPlv": {
				int newPlv = ToolList.getInt(1, cmds);
				int upLvl = player.getLevel();
				long totalExp = (LevelUpCfgCache.me().getById(player.getLevel()).getPlayerExp() - player.getExp());
				for (int i = upLvl + 1; i < newPlv; i++) {
					LevelUpCfg cfg = LevelUpCfgCache.me().getById(i);
					if (cfg == null) {
						break;
					}
					totalExp += cfg.getPlayerExp();
				}
				PlayerManager.me().addExp(player, totalExp);
				break;
			}
			case "addExp": {
				int exp = ToolList.getInt(1, cmds);
				PlayerManager.me().addExp(player, exp);
				break;
			}
			case "addHeroExp": {
				int exp = ToolList.getInt(1, cmds);
				Long heroId = ToolList.getLong(2, cmds);
				Hero hero = player.getPlayerProxy().getHerosByDbId().get(heroId);
				ToolError.isAndTrue(GameErrorCode.NOT_FOND_HERO, hero == null);
				HeroManager.me().addExp(exp, hero);
				break;
			}
			case "addTeamExp": {
				int exp = ToolList.getInt(1, cmds);
				HeroManager.me().addTeamExp(player, exp);
				break;
			}
			case "changeName": {
				String name = ToolList.getString(1, cmds);
				player.setName(name);
				player.update();

				PlayerInfo.Builder playerBuilder = PlayerInfo.newBuilder();
				playerBuilder.setName(player.getName());
				player.getPlayerProxy().sendMsg(
						MessageManager.me().create(Core.getPlayerInfo, ProtoUnit.toByte(playerBuilder.build())));
				break;
			}
			case "reloadScript": {
				Map<String, String> parameters = new HashMap<String, String>();
				if (cmds.size() > 1) {
					String scriptName = ToolList.getString(1, cmds);
					if (!"".equals(scriptName)) {
						parameters.put("file", scriptName);// 默认重载所有脚本，可指定重载单个脚本
					}
				}
				ScriptJavaLoader.getInstance().loadScript(parameters);
				break;
			}
			case "mc": {
				int goodsId = ToolList.getInt(1, cmds);
				GameRechargeManager.testDeliveryOrderGoods(player.getId(), UUID.randomUUID().toString(), goodsId);
				break;
			}
			case "room": {
				RoomTest.dispatcher(player, cmds);
				break;
			}
			case "allec": {
				byte b = 19;
				ElementCollectBO elementCollectBO = IServer.getModules().getModule(b, ElementCollectBO.class);
				elementCollectBO.getAllElement(player.getPlayerProxy().getSession(),
						C2SElementCollectMsg.GetAllElement.newBuilder().build());
				break;
			}
			case "dt": {// 约会
				DatingTest.dispatcher(player, cmds);
				break;
			}
			case "ro": {// 看板娘
				RoleTest.dispatcher(player, cmds);
				break;
			}
			case "build": {
				BuildingTest.dispatcher(player, cmds);
				break;
			}
			case "endlessLevel": {
				int level = ToolList.getInt(1, cmds);
				PlayerData playerData = player.getPlayerDatasFkPlayerId();
				PlayerDataProxy pdProxy = playerData.getPlayerDataProxy();
				EndlessVO endlessVO = pdProxy.getEndlessVO();
				int initLevelId = EndlessCloisterManager.me().getInitStageId();
				int newLevelId = initLevelId / 1000 * 1000 + level;
				EndlessCloisterLevelCfg cfg = EndlessCloisterLevelCfgCache.me().getById(newLevelId);
				if (cfg == null) {
					return false;
				}
				endlessVO.setLastPassTime(System.currentTimeMillis());
				// 计算下一关卡
				int nextStageId = newLevelId + 1;
				cfg = EndlessCloisterLevelCfgCache.me().getById(newLevelId);
				if (cfg == null) {
					nextStageId = -1;
				}
				endlessVO.setNowStage(nextStageId);
				int bestStage = newLevelId;// 今日最高通关关卡id
				endlessVO.setTodayBest(bestStage);// 因为后续要根据关卡id发奖，所以这里保存的是关卡id
				int best = EndlessCloisterLevelCfgCache.me().getById(bestStage).getOrder();
				if (best > endlessVO.getHistoryBest()) {
					endlessVO.setHistoryBest(best);
				}
				pdProxy.save();
				RspEndlessCloisterInfo info = EndlessCloisterMsgBuilder.createEndlessCloisterInfo(player);
				player.getPlayerProxy()
						.sendMsg(MessageManager.me().create(EndlessCloisterBO.getInfo, ProtoUnit.toByte(info)));

				List<RewardsMsg> rewards = new ArrayList<RewardsMsg>();
				RspPassStageEndless pInfo = EndlessCloisterMsgBuilder.createRspPassStageEndless(endlessVO, rewards,
						nextStageId);
				player.getPlayerProxy()
						.sendMsg(MessageManager.me().create(EndlessCloisterBO.passStage, ProtoUnit.toByte(pInfo)));
				break;
			}
			case "pass": {
				int cid = ToolList.getInt(1, cmds);
				DungeonLevelCfg levelCfg =  DungeonLevelCfgCache.me().getById(cid);
				ToolError.isAndTrue(GameErrorCode.CLIENT_PARAM_IS_ERR, levelCfg == null);
				pass(player, levelCfg);
				break;
			}
			case "passGroup": {
				int cid = ToolList.getInt(1, cmds);
				DungeonLevelGroupCfg group = DungeonLevelGroupCfgCache.me().getById(cid);
				ToolError.isAndTrue(GameErrorCode.CLIENT_PARAM_IS_ERR, group == null);
				passGroup(player, group);
				break;
			}
			case "passAll": {
				List<DungeonLevelGroupCfg> groups = DungeonLevelGroupCfgCache.me().getAll();
				for (DungeonLevelGroupCfg dungeonLevelGroupCfg : groups) {
					if (dungeonLevelGroupCfg.getDungeonType() == DungeonTypeConstant.DUNGEON_TYPE_MAIN_LINE || dungeonLevelGroupCfg.getDungeonType() == DungeonTypeConstant.DUNGEON_TYPE_GENERAL) {
						passGroup(player, dungeonLevelGroupCfg);
					}
				}
				break;
			}
			default:
				return false;
			}
			return true;
		} else {
			return false;
		}
	}

	private void passGroup(Player player, DungeonLevelGroupCfg group) {
		List<DungeonLevelCfg> levelCfgs = DungeonLevelCfgCache.me().getByLevelGroupId(group.getId());
		for (DungeonLevelCfg dungeonLevelCfg : levelCfgs) {
			pass(player, dungeonLevelCfg);
		}
	}

	private void pass(Player player, DungeonLevelCfg levelCfg) {
		int star = 3;
		
		// 主线
		List<MainLineCfg> mainLineCfgs = MainLineCfgCache.me().getByLevelGroupId(levelCfg.getLevelGroupId());
		int maxMainLineId = 0;
		for (MainLineCfg mainLineCfg : mainLineCfgs) {
			maxMainLineId = Math.max(maxMainLineId, mainLineCfg.getId());
		}
		
		MainLineCfg mainLineCfg = MainLineCfgCache.me().getById(maxMainLineId);
		// 取得最大的主线进度
		if (mainLineCfg != null) {
			DungeonLevelGroup group = DungeonManager.getOrInitDungeonLevelGroup(player, mainLineCfg.getLevelGroupId());
			group.setLastMainLine(mainLineCfg.getId());
			if (mainLineCfg.getId() > group.getMaxMainLine()){
			    group.setMaxMainLine(mainLineCfg.getId());
			}
			group.update();
			player.getPlayerProxy().sendMsg(DungeonBO.promoteStory, DungeonMsgBuilder.getProgressMsg(group));
		}
		
		List<Integer> achieveGoals = Lists.newArrayList();
		for (int i = 1; i <= star; i++) {
			achieveGoals.add(i);
		}
		
		
		
		// 关卡记录
		int oldStar = 0;
		int nowStar = star;
		DungeonLevel dungeonLevel = DungeonLevelCache.me().getDungeonLevelCacheProxy().getByPlayerIdCid(player.getId(), levelCfg.getId());
		if (dungeonLevel == null) {
			dungeonLevel = new DungeonLevel(0L, player.getId(), levelCfg.getId(), star, 1, true, achieveGoals, new Date(), 1);
			dungeonLevel = dungeonLevel.insert();
		}else {
			oldStar = dungeonLevel.getStar();
			dungeonLevel.setAchieveGoals(achieveGoals);
			dungeonLevel.setStar(star);
			dungeonLevel.update();
		}
		
		// 添加事件
		DungeonCheck.fightEvent(player, dungeonLevel, oldStar, nowStar, levelCfg, null);
		
		FightOverMsg fightOverMsg = DungeonMsgBuilder.getFightWinMsg(dungeonLevel, Lists.newArrayList());
		IMessage msg = MessageManager.me().create(DungeonBO.fightOver, fightOverMsg.toByteArray());
		player.getPlayerProxy().sendMsg(msg);
	}

	public static void main(String[] args) throws IOException {
		Runtime.getRuntime().exec("cmd /c time 03:00:00");
		System.out.println("ok");
	}

	// 设置系统时间
	private boolean setSystemDate(String date, String time) {
		boolean bool = false;
		try {
			DateTime dateTime = DateUtil.parse((date + " " + time).trim());

			ToolError.isAndTrue(GameErrorCode.CLIENT_PARAM_IS_ERR, dateTime.before(DateUtil.date()));
			if (SystemUtil.getOsInfo().isWindows()) {
				Runtime.getRuntime().exec("cmd /c date " + date);
				Runtime.getRuntime().exec("cmd /c time " + time);
				bool = true;
			} else if (SystemUtil.getOsInfo().isLinux()) {
				Runtime.getRuntime().exec("date -s " + date);
				Runtime.getRuntime().exec("date -s " + time);
				bool = true;
			}

			if (bool) {
				Thread.sleep(100);
			}
		} catch (Exception e) {
			log.error(e);
		}
		return bool;
	}

	/** 公告系统时间 */
	private IMessage notifySystemDate(String content) {
		ChatInfo.Builder builder = ChatInfo.newBuilder();
		builder.setChannel(ChatConstant.CHANNEL_SYSTEM);
		builder.setFun(ChatConstant.FUN_CHAT);
		builder.setContent(content);
		builder.setPid(0);
		builder.setPname("System");
		builder.setLvl(0);
		builder.setHelpFightHeroCid(0);
		IMessage msg = MessageManager.me().create(ChatBO.pushChatMsg, builder.build().toByteArray());
		return msg;
	}
}
